﻿#include "hyTool.h"
#include <stdexcept>

namespace SDHuaYi_Utils
{

    HYString::HYString()
    {
    }

    quint8 HYString::getByte(QString str)
    {
        if (str.count() != 2)
            throw std::runtime_error("func:getByte str.count err");

        bool ok;
        quint8 hex = str.toInt(&ok, 16);
        if (!ok)
            throw std::runtime_error("func:getByte toInt err");

        return hex;
    }

    QString HYString::getStr(quint8 hex)
    {
        QString str = QString();

        str = QString::number(hex).rightJustified(2, '0');

        return str;
    }

    QString HYString::byteArray2String(QByteArray byte_array, qint32 len)
    {
        QString str;
#if 0
        if(byte_array.count()!=len)
        {
            throw std::runtime_error("func:byteArray2String length err");
        }

        for(char byte:byte_array)
        {
            QString byteHexString = QString("%1").arg(static_cast<int>(byte),2,16,QLatin1Char('0')).toUpper();
            str.append(byteHexString);
        }
#else
        for (int i = 0; i < len; i++)
        {
            str += getStr(byte_array[i]);
        }
#endif
        return str;
    }

    qint32 HYString::string2byteArray(QString str, QByteArray &byteArray, qint32 offset)
    {
        str = str.replace(" ", "");
        if (str.count() % 2 != 0)
        {
            str = "0" + str;
        }
        for (int i = 0; i < str.count(); i += 2)
        {
            byteArray[i / 2 + offset] = getByte(str.mid(i, 2));
        }
        return str.count() / 2;
    }

    QByteArray HYString::string2byteArray(QString str)
    {
        str = str.replace(" ", "");

        if (str.count() % 2 != 0)
        {
            throw std::runtime_error("字符串长度错误");
        }
        QByteArray byteArray(str.count() / 2, 0);

        for (int i = 0; i < str.count(); i += 2)
        {
            byteArray[i / 2] = getByte(str.mid(i, 2));
        }
        return byteArray;
    }

    QString HYString::strxor(QString str1, QString str2)
    {
        QByteArray byteArr1(str1.count() / 2, 0);
        QByteArray byteArr2(str2.count() / 2, 0);

        string2byteArray(str1, byteArr1);
        string2byteArray(str2, byteArr2);
        int xor_len = str1.count() >= str2.count() ? str2.count() : str1.count();
        QByteArray xor_array = str1.count() >= str2.count() ? byteArr2 : byteArr1;

        for (int i = 0; i < xor_len / 2; i++)
        {
            xor_array[i] = byteArr1[i] ^ byteArr2[i];
        }
        return byteArray2String(xor_array, xor_array.count());
    }

    QString HYString::stradd(QString str1, QString str2)
    {
        QString optr1 = str1;
        QString optr2 = str2;

        if (str1.count() < str2.count())
        {
            optr1 = str2;
            optr2 = str1;
        }

        int i = 0;
        for (i = 0; i < str1.count() / 2 - str2.count() / 2; i++)
        {
            // 补00
            optr2 = "00" + optr2;
        }

        QByteArray bstr1(optr1.count() / 2, 0);
        QByteArray bstr2(optr2.count() / 2, 0);

        string2byteArray(optr1, bstr1);
        string2byteArray(optr2, bstr2);

        quint8 c_byte = 0;

        for (i = bstr1.count() - 1; i >= 0; i--)
        {
            short result = (short)((short)bstr1[i] + (short)bstr2[i] + c_byte);
            if (result > 0xFF)
            {
                c_byte = 1;
            }

            bstr1[i] = (quint8)(result & 0xFF);
        }

        return byteArray2String(bstr1, bstr1.count());
    }

    qint32 HYString::calc_checksum(QByteArray byteArray, qint32 len)
    {
        int cksum = 0;

        for (int i = 0; i < len; i++)
        {
            cksum += byteArray[i];
        }

        return cksum;
    }

    QByteArray HYString::int2byteArray(qint32 iA)
    {
        QByteArray bytArr(4, 0);

        bytArr[3] = (quint8)(iA & 0xFF);
        bytArr[2] = (quint8)((iA >> 8) & 0xFF);
        bytArr[1] = (quint8)((iA >> 16) & 0xFF);
        bytArr[0] = (quint8)((iA >> 24) & 0xFF);

        return bytArr;
    }

    qint32 HYString::byteArray2int(QByteArray bytArr)
    {
        int iA = 0;
        for (int i = 0; i < bytArr.count(); i++)
        {
            iA = (iA << 8) + bytArr[i];
        }
        return iA;
    }

    QString HYString::int2string(qint32 iINT, qint32 len)
    {
        QByteArray bytarr = int2byteArray(iINT);

        QString str = byteArray2String(bytarr, 4);

        if (len > 8)
        {
            len = 8;
        }
        return str.mid(8 - len);
    }

    qint32 HYString::string2int(QString strINT)
    {
        strINT = strINT.replace(" ", "");

        if (strINT.count() % 2 != 0)
        {
            strINT = "0" + strINT;
        }

        QByteArray bytArr(strINT.count() / 2, 0);

        string2byteArray(strINT, bytArr);

        return byteArray2int(bytArr);
    }

    qint32 HYString::stringCompare(QString stringA, QString stringB)
    {
        QByteArray byteArrA(1024, 0);
        QByteArray byteArrB(1024, 0);

        int byteAlen = string2byteArray(stringA, byteArrA, 0);
        int byteBlen = string2byteArray(stringB, byteArrB, 0);

        if (byteAlen != byteBlen)
        {
            if (byteAlen > byteBlen)
            {
                return 1;
            }
            else
            {
                return -1;
            }
        }
        else
        {
            for (int i = 0; i < byteAlen; i++)
            {
                if (byteArrA[i] > byteArrB[i])
                {
                    return 1;
                }
                if (byteArrA[i] < byteArrB[i])
                {
                    return -1;
                }
            }
            return 0;
        }
    }
    int countOnesInByte(quint8 byte)
    {
        int count = 0;
        while (byte)
        {
            count += byte & 1;
            byte >>= 1;
        }
        return count;
    }
    bool HYString::adjustParityBitsToOdd(QString &hexStr)
    {
        int count = 0;
        if (hexStr.count() % 2 != 0)
        {
            throw std::runtime_error("adjustParityBitsToOdd lenght err");
        }

        // 遍历
        for (int i = 0; i < hexStr.count(); i += 2)
        {
            QString byteStr = hexStr.mid(i, 2);
            bool ok;
            quint8 byte = byteStr.toLatin1().toUInt(&ok, 16);
            if (!ok)
            {
                throw std::runtime_error("adjustParityBitsToOdd byteStr err");
            }
            count = countOnesInByte(byte);

            if (count % 2 == 1)
                continue;

            byte ^= 1;

            hexStr.replace(i, 2, QString("%1").arg(byte, 2, 16, QChar('0')));
        }
        return true;
    }
}
